package com.nhc.activity_fragment;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.astrob.NavFrameSDK;
import com.astrob.model.LonLat;
import com.astrob.model.Msg;
import com.astrob.naviframe.Start;
import com.astrob.nhcmap.R;
import com.astrob.util.SysUtils;
import com.astrob.util.Utils;
import com.astrob.view.Compass;
import com.astrob.view.TrackShow;
import com.astrob.view.ZoomView;
import com.nhc.database.dbmodel.TrackPoint;
import com.nhc.database.dbmodel.WayPoint;
import com.nhc.database.dbmodel.WayTrail;
import com.nhc.database.manager.DBDataCenter;
import com.nhc.model.MapSetInfo;
import com.nhc.view.MultiMapView;

import org.osmdroid.api.IGeoPoint;
import org.osmdroid.events.MapListener;
import org.osmdroid.events.ScrollEvent;
import org.osmdroid.events.ZoomEvent;
import org.osmdroid.tileprovider.cachemanager.CacheManager;
import org.osmdroid.tileprovider.modules.IFilesystemCache;
import org.osmdroid.tileprovider.modules.SqlTileWriter;
import org.osmdroid.tileprovider.modules.SqliteArchiveTileWriter;
import org.osmdroid.tileprovider.modules.TileWriter;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.Projection;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.Polygon;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class DownloadMapActivity extends Activity implements View.OnClickListener {

    public static final String INTENT_DOWNLOADMAP_MODE = "INTENT_DOWNLOADMAP_MODE";


    public static Intent createIntent(Context context, int mode) {
        return new Intent(context, DownloadMapActivity.class)
                .putExtra(INTENT_DOWNLOADMAP_MODE, mode);
    }


    int _mode = 0;//0-   1-  2-使用编辑航迹
    ZoomView mZoom;
    TextView tv_next;
    TextView mLocal;
    MultiMapView mMultiMapView;

    TextView tv_search;
    TextView tv_tile;

    int _mapsource = 1;//只能显示在线图
    LonLat _centerLL;
    Compass mCompass = new Compass();
    private WayTrail wayTrailEdit = null;

    TextView tv_selfdraw;
    boolean _isSelfdraw = false;//下载区域设定的模式

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.downloadmap_activity);

        mMultiMapView = (MultiMapView) findViewById(R.id.id_multimap);
        if (SysUtils.getInstance().mapsource < 1000) {
            _mapsource = SysUtils.getInstance().mapsource;
        }
        mMultiMapView.setMapsource(_mapsource);
        initMapEngin();

        mZoom = (ZoomView) findViewById(R.id.id_zoomview);
        tv_next = (TextView) findViewById(R.id.tv_next);
        mLocal = (TextView) findViewById(R.id.btnlocal);

        tv_search = (TextView) findViewById(R.id.tv_search);
        tv_tile = (TextView) findViewById(R.id.tv_tile);
        tv_tile.setText(mMultiMapView.getMapsourceStr(_mapsource));
        tv_selfdraw = (TextView) findViewById(R.id.tv_selfdraw);

        onChangeSelfdraw(_isSelfdraw);

        mZoom.setOnClickListener(this);
        mLocal.setOnClickListener(this);
        tv_selfdraw.setOnClickListener(this);

        findViewById(R.id.btn_measure_addone).setOnClickListener(this);
        findViewById(R.id.btn_measure_closeone).setOnClickListener(this);

        tv_next.setOnClickListener(this);
        tv_search.setOnClickListener(this);
        tv_tile.setOnClickListener(this);
        _mode = getIntent().getIntExtra(INTENT_DOWNLOADMAP_MODE, _mode);

        _centerLL = SysUtils.getInstance().getLL();
        mMultiMapView.setMapOrientation(0);
        mMultiMapView.setScale(50000);
        mMultiMapView.setMapCenter(_centerLL);

        if (_mode == 2) {
            wayTrailEdit = DBDataCenter.getInstance().wayTrailEdit;
            setMapByWayTrail();
        }

    }

    void onChangeSelfdraw(boolean isSelfdraw) {
        mMeasurelist.clear();

        _isSelfdraw = isSelfdraw;
        if (_isSelfdraw) {
            tv_selfdraw.setText("自绘\n区域");
            findViewById(R.id.tv_selfctrl).setVisibility(View.VISIBLE);
        } else {
            tv_selfdraw.setText("固定屏幕区域");
            findViewById(R.id.tv_selfctrl).setVisibility(View.GONE);
        }
        updateMapView();
    }


    void setMapByWayTrail() {
        if (wayTrailEdit == null) {
            return;
        }
        if (wayTrailEdit.trackPointList == null) {
            wayTrailEdit.trackPointList = DBDataCenter.getInstance().getTrackPointByWayTrail(wayTrailEdit, null);
        }

        if (wayTrailEdit.trackPointList.size() < 1) {
            return;
        }

        double MinLon = 10000;
        double MinLat = 10000;
        double MaxLon = -1000;
        double MaxLat = -1000;

        List<GeoPoint> points = new ArrayList<>();
        for (int i = 0; i < wayTrailEdit.trackPointList.size(); i++) {
            TrackPoint tp = wayTrailEdit.trackPointList.get(i);
            LonLat poiLL = tp.getLL();
            if (poiLL.GetLon() < MinLon) {
                MinLon = poiLL.GetLon();
            }

            if (poiLL.GetLat() < MinLat) {
                MinLat = poiLL.GetLat();
            }

            if (poiLL.GetLon() > MaxLon) {
                MaxLon = poiLL.GetLon();
            }

            if (poiLL.GetLat() > MaxLat) {
                MaxLat = poiLL.GetLat();
            }

            points.add(new GeoPoint(poiLL.GetLat(), poiLL.GetLon()));
        }

        _centerLL = new LonLat((MinLon + MaxLon) / 2, (MinLat + MaxLat) / 2);
        mMultiMapView.setMapOrientation(0);
        mMultiMapView.setMapCenter(_centerLL);

        LonLat posA = new LonLat(MinLon, MinLat);
        LonLat posB = new LonLat(MaxLon, MaxLat);
        double distance = Start.getInstance().MapKit().getDistance(posA, posB);

        if (distance < 500) {
            mMultiMapView.mMapViewOnline.getController().setZoom(16);
        } else if (distance < 1000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(15);
        } else if (distance < 2000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(14);
        } else if (distance < 4000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(13);
        } else if (distance < 8000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(12);
        } else if (distance < 16000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(11);
        } else if (distance < 32000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(10);
        } else if (distance < 64000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(9);
        } else if (distance < 128000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(8);
        } else if (distance < 256000) {
            mMultiMapView.mMapViewOnline.getController().setZoom(7);
        } else {
            mMultiMapView.mMapViewOnline.getController().setZoom(6);
        }

    }


    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case Msg.UPDATEMAP:
                    updateMapView();
                    break;
                case Msg.FINISHUPDATEMAP:
                    finishUpdatedMapView();
                    break;
            }
        }
    };

    private void updateMapView() {
        mMultiMapView.updateMap();
    }

    private void finishUpdatedMapView() {
        if (mMultiMapView.getMapsource() != 1000) {
            mZoom.updateState(0);
        } else {
            mZoom.updateState();
        }
    }

    public void onReturnClick(View v) {
        finish();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnzoomin:
                onZoomIn();
                break;
            case R.id.btnzoomout:
                onZoomOut();
                break;
            case R.id.tv_next:
                onNext();
                break;
            case R.id.btnlocal:
                onLocal();
                break;
            case R.id.tv_search:
//                onLoadgpx();
                onSearch();
                break;
            case R.id.tv_tile:
                onChangeTile();
                break;
            case R.id.tv_selfdraw:
                onChangeSelfdraw(!_isSelfdraw);
                break;
            case R.id.btn_measure_addone:
                measureAddone();
                break;
            case R.id.btn_measure_closeone:
                measureCloseone();
                break;
            default:
                break;
        }
    }

    private void onSearch() {
        startActivityForResult(SearchTypeActivity.createIntent(this, true), REQUEST_TO_SEARCH);
    }

    ArrayList<LonLat> mMeasurelist = new ArrayList<LonLat>();

    private void measureAddone() {
        LonLat ll = mMultiMapView.getMapCenter();

        if (mMultiMapView.isgcj02) {
            ll = Utils.gcj02towgs84(ll.GetLon(), ll.GetLat());
        }

        mMeasurelist.add(ll);
        updateMapView();
    }

    private void measureCloseone() {
        int size = mMeasurelist.size();
        if (size < 1)
            return;

        mMeasurelist.remove(size - 1);
        updateMapView();
    }

    void onLoadgpx() {

    }

    void onChangeTile() {
        _mapsource++;
        if (_mapsource > 3) {
            _mapsource = 0;
        }
        mMultiMapView.setMapsource(_mapsource);
        tv_tile.setText(mMultiMapView.getMapsourceStr(_mapsource));

        mMultiMapView.setMapOrientation(0);
        mMultiMapView.setMapCenter(_centerLL);
        updateMapView();

    }

    private void onNext() {
        startActivityForResult(DownloadMapSetActivity.createIntent(this), REQUEST_CODE_DOWNLOADMPSET);
    }

    public static final int REQUEST_CODE_DOWNLOADMPSET = 18;
    private final int REQUEST_TO_SEARCH = 32;

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_CODE_DOWNLOADMPSET) {
            if (SysUtils.getInstance().downloadmapdbname.length() > 0) {
                downLoad(SysUtils.getInstance().pZoomMin, SysUtils.getInstance().pZoomMax);
                setResult(RESULT_OK);
            }

        }

        if (requestCode == REQUEST_TO_SEARCH) {
            if (resultCode == Msg.SEACHSELECTEDONE) {
                if (DBDataCenter.getInstance().makerSeach != null) {
                    WayPoint wp = DBDataCenter.getInstance().makerSeach;
                    NavFrameSDK.POIDescription poiData = NavFrameSDK.getInstance().new POIDescription();
                    poiData.name = wp.getName();
                    poiData.position.lon = wp.getLL().GetLon();
                    poiData.position.lat = wp.getLL().GetLat();
                    mMultiMapView.setMapCenter(wp.getLL());
                    mMultiMapView.setScale(100000);
                    updateMapView();
                }
                return;
            }
        }
    }

    //离线地图下载
    private void downLoad(int pZoomMin, int pZoomMax) {
//        if (!_isSelfdraw) {
//            downLoad2(pZoomMin, pZoomMax);
//            return;
//        }

        ArrayList<GeoPoint> points = new ArrayList<>();
        for (int i = 0; i < mMeasurelist.size(); ++i) {
            LonLat poiLL = mMeasurelist.get(i);
            if (mMultiMapView.isgcj02) {
                poiLL = Utils.wgs84togcj02(poiLL.GetLon(), poiLL.GetLat());//Utils GPS to 火星坐标
            }
            points.add(new GeoPoint(poiLL.GetLat(), poiLL.GetLon()));
        }

        String strDir = Environment.getExternalStorageDirectory() + "/BHCMapper/offline/";
        if (SysUtils.getInstance().is240x320) {
            strDir = "/mnt/sdcard2/BHCMapper/offline/";
        }
        File filedir = new File(strDir);
        if (!filedir.exists()) {
            strDir = Environment.getExternalStorageDirectory() + "/BHCMapper/offline/";
            File filedir2 = new File(strDir);
            filedir2.mkdirs();
        }
        String outputFile = strDir + SysUtils.getInstance().downloadmapdbname + ".sqlite";
        IFilesystemCache mWriter = null;
        try {
            mWriter = new SqliteArchiveTileWriter(outputFile);
        } catch (Exception e) {
            Toast.makeText(DownloadMapActivity.this, e.toString(), Toast.LENGTH_SHORT).show();
            return;
        }

        CacheManager cacheManager = new CacheManager(mMultiMapView.mMapViewOnline, mWriter);//获取下载器
        int tileNum = cacheManager.possibleTilesCovered(points, pZoomMin, pZoomMax);//计算当前区域8-16级的瓦片数量
        final CacheManager.CacheManagerTask cacheManagerTask = cacheManager.downloadAreaAsync(this, points, pZoomMin, pZoomMax,
                new CacheManager.CacheManagerCallback() {
                    @Override
                    public void updateProgress(int progress, int currentZoomLevel, int zoomMin, int zoomMax) {

                    }

                    @Override
                    public void downloadStarted() {

                    }

                    @Override
                    public void setPossibleTilesInArea(int total) {

                    }

                    @Override
                    public void onTaskFailed(int errors) {

                        errors = 0;
                    }//下载

                    @Override
                    public void onTaskComplete() {
                        //下载完成后的回调
                        SysUtils.getInstance().downloadmapdbname = "";
                        Toast.makeText(DownloadMapActivity.this, "已下载完成！", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    private void downLoad2(int pZoomMin, int pZoomMax) {
        ArrayList<GeoPoint> points = new ArrayList<>();
        for (int i = 0; i < mMeasurelist.size(); ++i) {
            LonLat poiLL = mMeasurelist.get(i);
            if (mMultiMapView.isgcj02) {
                poiLL = Utils.wgs84togcj02(poiLL.GetLon(), poiLL.GetLat());//Utils GPS to 火星坐标
            }
            points.add(new GeoPoint(poiLL.GetLat(), poiLL.GetLon()));
        }

        BoundingBox boundingBoxE6 = BoundingBox.fromGeoPoints(points);//获取当前区域
        String strDir = Environment.getExternalStorageDirectory() + "/BHCMapper/offline/";
        File filedir = new File(strDir);
        if (!filedir.exists()) {
            filedir.mkdirs();
        }
        String outputFile = strDir + SysUtils.getInstance().downloadmapdbname + ".sqlite";
        IFilesystemCache mWriter = null;
        try {
            mWriter = new SqliteArchiveTileWriter(outputFile);
        } catch (Exception e) {
            Toast.makeText(DownloadMapActivity.this, e.toString(), Toast.LENGTH_SHORT).show();
            return;
        }

        CacheManager cacheManager = new CacheManager(mMultiMapView.mMapViewOnline, mWriter);//获取下载器
        int tileNum = cacheManager.possibleTilesInArea(boundingBoxE6, pZoomMin, pZoomMax);//计算当前区域8-16级的瓦片数量
        int tileNum2 = cacheManager.possibleTilesCovered(points, pZoomMin, pZoomMax);//计算当前区域8-16级的瓦片数量

        final CacheManager.CacheManagerTask cacheManagerTask = cacheManager.downloadAreaAsync(this, boundingBoxE6, pZoomMin, pZoomMax,
                new CacheManager.CacheManagerCallback() {
                    @Override
                    public void updateProgress(int progress, int currentZoomLevel, int zoomMin, int zoomMax) {

                    }

                    @Override
                    public void downloadStarted() {

                    }

                    @Override
                    public void setPossibleTilesInArea(int total) {

                    }

                    @Override
                    public void onTaskFailed(int errors) {
                        errors = 0;
                    }//下载

                    @Override
                    public void onTaskComplete() {
                        //下载完成后的回调
                        SysUtils.getInstance().downloadmapdbname = "";
                        Toast.makeText(DownloadMapActivity.this, "已下载完成！", Toast.LENGTH_SHORT).show();
                    }
                });
    }

    void onZoomIn() {
        mMultiMapView.zoomIn();
        mMultiMapView.updateMap();
    }

    void onZoomOut() {
        mMultiMapView.zoomOut();
        mMultiMapView.updateMap();
    }

    void onLocal() {
        if (Utils.isFastDoubleClick())
            return;

        mMultiMapView.setMapCenter(_centerLL);
        mMultiMapView.setScale(100000);
        mMultiMapView.updateMap();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
            default:
                break;
            case 21://left
                mMultiMapView.moveMap(-5, 0);
                return true;
            case 22://right
                mMultiMapView.moveMap(5, 0);
                return true;
            case 19://up
                mMultiMapView.moveMap(0, -5);
                return true;
            case 20://down
                mMultiMapView.moveMap(0, 5);
                return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        switch (keyCode) {
            default:
                break;
            case 23://ok
                break;
            case KeyEvent.KEYCODE_BACK:
                finish();
                break;
            case 24://Zoomin
                if (!SysUtils.getInstance().is240x320) {
                    return true;
                }
                onZoomIn();
                return true;
            case 25://Zoomout
                if (!SysUtils.getInstance().is240x320) {
                    return true;
                }
                onZoomOut();
                return true;
        }

        return super.onKeyUp(keyCode, event);
    }

    @Override
    public void onDestroy() {
        mMultiMapView.destroyMap();
        super.onDestroy();
    }

    //====================
    private void initMapEngin() {
        mGisOverlay = new CustomPointOverlay();
        mMultiMapView.mMapViewOnline.getOverlays().add(mGisOverlay);
    }

    //======OSM
    MapListener mapListener = new MapListener() {
        @Override
        public boolean onScroll(ScrollEvent scrollEvent) {
            return true;
        }

        @Override
        public boolean onZoom(ZoomEvent zoomEvent) {
            return false;
        }

        @Override
        public void longPress(Point pt) {
            if (pt == null) {
                return;
            }
        }

        //双击
        @Override
        public void doubleClick(Point pt) {
            if (pt == null) {
                return;
            }
        }

        //单击 单击后
        @Override
        public void singleClick(Point pt) {
            if (pt == null) {
                return;
            }
        }

        //移图后抬起
        @Override
        public void touchUp() {
        }

        //手指移动-切换到移图模式
        @Override
        public void moveMap() {
        }

    };

    private CustomPointOverlay mGisOverlay = null;

    public class CustomPointOverlay extends Overlay {
        public CustomPointOverlay() {
        }

        List<Point> rectlist = new ArrayList<>();

        @Override
        public void draw(Canvas canvas, MapView mapView, boolean shadow) {

            MapSetInfo.getInstance().draw2(getBaseContext(), canvas, mapView);
            mCompass.draw2(getBaseContext(), canvas, (int) mapView.getMapOrientation());

            if (wayTrailEdit != null) {
                TrackShow.getInstance().drawWayTrail2(getBaseContext(), canvas, mapView, wayTrailEdit, mMultiMapView.isgcj02);
            }

            drawDRect(canvas, mapView, shadow);

            drawMeasure2(canvas, mapView, shadow);//自绘区域
            //画完图
            mHandler.sendEmptyMessage(Msg.FINISHUPDATEMAP);
        }

        //固定屏幕下载区域
        void drawDRect(Canvas canvas, MapView mapView, boolean shadow) {

            if (_isSelfdraw) {
                return;
            }
            int XC = canvas.getWidth() / 2;
            int YC = canvas.getHeight() / 2;
            int R = canvas.getWidth() / 4;
//            if (rectlist.size() < 1) {
//                rectlist.add(new Point(XC-R, YC-R));//0 左上
//                rectlist.add(new Point(XC+R, YC-R));//1 右上
//                rectlist.add(new Point(XC+R, YC+R));//2 右下
//                rectlist.add(new Point(XC-R, YC+R));//3 左下
//            }

            Paint paint = new Paint();
            paint.reset();
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(1);
            paint.setColor(Color.parseColor("#8800EE00"));
            paint.setStyle(Paint.Style.FILL);
            paint.setAntiAlias(true);

            Path path = new Path();
            path.moveTo(XC - R, YC - R);
            path.lineTo(XC + R, YC - R);
            path.lineTo(XC + R, YC + R);
            path.lineTo(XC - R, YC + R);
            path.close();

            canvas.drawPath(path, paint);

            mMeasurelist.clear();

            mMeasurelist.add(getLLByXY(XC - R, YC - R));
            mMeasurelist.add(getLLByXY(XC + R, YC - R));
            mMeasurelist.add(getLLByXY(XC + R, YC + R));
            mMeasurelist.add(getLLByXY(XC - R, YC + R));
        }

        LonLat getLLByXY(int x, int y) {
            IGeoPoint geoPoint = mMultiMapView.mMapViewOnline.getProjection().fromPixels(x, y);
            LonLat poiLL = new LonLat(geoPoint.getLongitude(), geoPoint.getLatitude());
            if (mMultiMapView.isgcj02) {
                poiLL = Utils.gcj02towgs84(poiLL.GetLon(), poiLL.GetLat());
            }
            return poiLL;
        }


        void drawMeasure2(Canvas canvas, MapView mapView, boolean shadow) {

            if (!_isSelfdraw) {
                return;
            }

            int count = mMeasurelist.size();
            if (count < 1) {
                return;
            }

            List<GeoPoint> points = new ArrayList<>();
            List<Point> ptlist = new ArrayList<>();
            for (int i = 0; i < count; ++i) {
                LonLat poiLL = mMeasurelist.get(i);
                if (mMultiMapView.isgcj02) {
                    poiLL = Utils.wgs84togcj02(poiLL.GetLon(), poiLL.GetLat());//Utils GPS to 火星坐标
                }
                points.add(new GeoPoint(poiLL.GetLat(), poiLL.GetLon()));
                Point ff = LL2XY(poiLL);
                ptlist.add(ff);
            }

            Polygon polygon = new Polygon();
            Paint paint = polygon.getOutlinePaint();
            paint.reset();
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(3);
            paint.setAntiAlias(true);

            polygon.setFillColor(Color.parseColor("#8800EE00"));
            polygon.setPoints(points);
            polygon.draw(canvas, mapView, shadow);

            paint = new Paint();
            for (int i = 0; i < count; ++i) {
                Point ff = ptlist.get(i);
                paint.setStyle(Paint.Style.FILL);
                paint.setColor(Color.parseColor("#AAFF0000"));
                canvas.drawCircle(ff.x, ff.y, dip2px(12), paint);

                String strPrn = (i + 1) + "";
                float textWidth = paint.measureText(strPrn) / 2;
                float textHeight = paint.getTextSize() / 2;
                paint.setColor(Color.WHITE);
                paint.setTextSize(13);
                paint.setFakeBoldText(true);
                canvas.drawText(strPrn, ff.x - textWidth, ff.y + textHeight - 1,
                        paint);
            }

        }

        private final Point mMapCoordsProjected = new Point();

        Point LL2XY(LonLat ll) {
            Point B = new Point();
            mMultiMapView.mMapViewOnline.getProjection().toProjectedPixels(ll.GetLat(),
                    ll.GetLon(), mMapCoordsProjected);
            Projection pj = mMultiMapView.mMapViewOnline.getProjection();
            pj.toPixelsFromProjected(mMapCoordsProjected, B);
            return B;
        }


    }

    int dip2px(int dip) {
        return Utils.dip2px(this, dip);
    }

}
